﻿using System;
using System.Collections;
using System.Collections.Generic;

namespace duocon.data
{
    internal class DuoconDictionary<TKey, TValue> : IEnumerable<KeyValuePair<TKey, TValue>>
    {
        private const int DefaultConcurrencyLevel = 16; // 默认分段数
        private readonly DuoconSegment<TKey, TValue>[] _segments;
        private readonly IEqualityComparer<TKey> _comparer;

        public DuoconDictionary(int concurrencyLevel = DefaultConcurrencyLevel, int initialCapacity = 0, IEqualityComparer<TKey> comparer = null)
        {
            _comparer = comparer ?? EqualityComparer<TKey>.Default;
            concurrencyLevel = Math.Max(1, Math.Min(concurrencyLevel, 65536)); // 限制分段数范围
            _segments = new DuoconSegment<TKey, TValue>[concurrencyLevel];

            int segmentCapacity = initialCapacity / concurrencyLevel;
            for (int i = 0; i < concurrencyLevel; i++)
            {
                _segments[i] = new DuoconSegment<TKey, TValue>(segmentCapacity > 0 ? segmentCapacity : 1);
            }
        }

        // 根据键的哈希值确定分段索引
        private int GetSegmentIndex(TKey key)
        {
            int hash = _comparer.GetHashCode(key) & 0x7FFFFFFF; // 确保非负
            return hash % _segments.Length;
        }

        public void AddOrUpdate(TKey key, TValue value)
        {
            int segmentIndex = GetSegmentIndex(key);
            _segments[segmentIndex].AddOrUpdate(key, value);
        }

        public bool TryGetValue(TKey key, out TValue value)
        {
            int segmentIndex = GetSegmentIndex(key);
            return _segments[segmentIndex].TryGetValue(key, out value);
        }

        public bool Remove(TKey key)
        {
            int segmentIndex = GetSegmentIndex(key);
            return _segments[segmentIndex].Remove(key);
        }

        public TValue this[TKey key]
        {
            get
            {
                int segmentIndex = GetSegmentIndex(key);
                return _segments[segmentIndex][key];
            }
            set
            {
                int segmentIndex = GetSegmentIndex(key);
                _segments[segmentIndex][key] = value;
            }
        }

        public int Count
        {
            get
            {
                int count = 0;
                foreach (var segment in _segments)
                    lock (segment) // 注意：此处需加锁保证计数准确
                        count += segment.Count;
                return count;
            }
        }

        // 枚举所有键值对（返回全局快照）
        public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
        {
            // 对每个分段加锁，复制数据到临时列表
            var snapshots = new List<KeyValuePair<TKey, TValue>>[_segments.Length];
            for (int i = 0; i < _segments.Length; i++)
                lock (_segments[i])
                    snapshots[i] = new List<KeyValuePair<TKey, TValue>>(_segments[i]._dict);

            // 合并所有分段的快照
            foreach (var snapshot in snapshots)
                foreach (var kvp in snapshot)
                    yield return kvp;
        }

        IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
    }
}
